package com.ruoyi.system.service.impl;

import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import com.ruoyi.common.utils.StringUtils;
import org.springframework.transaction.annotation.Transactional;
import com.ruoyi.system.domain.BizInspectionResult;
import com.ruoyi.system.mapper.BizInspectionPlanMapper;
import com.ruoyi.system.domain.BizInspectionPlan;
import com.ruoyi.system.service.IBizInspectionPlanService;
import com.ruoyi.system.service.IBizPurchaseReturnService;

/**
 * 来料检验计划Service业务层处理
 * 
 * @author ruoyi
 * @date 2025-10-30
 */
@Service
public class BizInspectionPlanServiceImpl implements IBizInspectionPlanService 
{
    @Autowired
    private BizInspectionPlanMapper bizInspectionPlanMapper;

    @Autowired
    private com.ruoyi.system.mapper.BizBarcodeMapper bizBarcodeMapper;

    @Autowired
    private com.ruoyi.system.mapper.BizPurchaseOrderMapper bizPurchaseOrderMapper;

    @Autowired
    private com.ruoyi.system.mapper.BizReceiptNoteMapper bizReceiptNoteMapper;

    @Autowired
    private com.ruoyi.system.mapper.BizDeliveryNoteMapper bizDeliveryNoteMapper;

    @Autowired
    private IBizPurchaseReturnService bizPurchaseReturnService;

    /**
     * 查询来料检验计划
     * 
     * @param planId 来料检验计划主键
     * @return 来料检验计划
     */
    @Override
    public BizInspectionPlan selectBizInspectionPlanByPlanId(Long planId)
    {
        return bizInspectionPlanMapper.selectBizInspectionPlanByPlanId(planId);
    }

    /**
     * 查询来料检验计划列表
     * 
     * @param bizInspectionPlan 来料检验计划
     * @return 来料检验计划
     */
    @Override
    public List<BizInspectionPlan> selectBizInspectionPlanList(BizInspectionPlan bizInspectionPlan)
    {
        return bizInspectionPlanMapper.selectBizInspectionPlanList(bizInspectionPlan);
    }

    /**
     * 新增来料检验计划
     * 
     * @param bizInspectionPlan 来料检验计划
     * @return 结果
     */
    @Transactional
    @Override
    public int insertBizInspectionPlan(BizInspectionPlan bizInspectionPlan)
    {
        int rows = bizInspectionPlanMapper.insertBizInspectionPlan(bizInspectionPlan);
        insertBizInspectionResult(bizInspectionPlan);
        return rows;
    }

    /**
     * 修改来料检验计划
     * 
     * @param bizInspectionPlan 来料检验计划
     * @return 结果
     */
    @Transactional
    @Override
    public int updateBizInspectionPlan(BizInspectionPlan bizInspectionPlan)
    {
        bizInspectionPlanMapper.deleteBizInspectionResultByPlanId(bizInspectionPlan.getPlanId());
        insertBizInspectionResult(bizInspectionPlan);
        int rows = bizInspectionPlanMapper.updateBizInspectionPlan(bizInspectionPlan);

        // 若此次更新标记为拒收（计划状态=REJECTED 或 检验结果=FAILED），则：
        // 1) 基于检验计划生成退料单（避免重复生成，若已存在则跳过）
        // 2) 触发拒收回滚，恢复到采购订单生成箱码阶段，并将箱码置为拒收
        boolean isRejected =
            (com.ruoyi.common.utils.StringUtils.isNotEmpty(bizInspectionPlan.getPlanStatus())
                && "REJECTED".equalsIgnoreCase(bizInspectionPlan.getPlanStatus()))
            || (com.ruoyi.common.utils.StringUtils.isNotEmpty(bizInspectionPlan.getInspectionResult())
                && ("FAIL".equalsIgnoreCase(bizInspectionPlan.getInspectionResult())
                    || "FAILED".equalsIgnoreCase(bizInspectionPlan.getInspectionResult())));

        if (isRejected && com.ruoyi.common.utils.StringUtils.isNotEmpty(bizInspectionPlan.getPlanNo())) {
            // 避免重复生成退料单：按检验计划号查询是否已存在
            com.ruoyi.system.domain.BizPurchaseReturn retQuery = new com.ruoyi.system.domain.BizPurchaseReturn();
            retQuery.setInspectionPlanNo(bizInspectionPlan.getPlanNo());
            java.util.List<com.ruoyi.system.domain.BizPurchaseReturn> existing =
                bizPurchaseReturnService.selectBizPurchaseReturnList(retQuery);
            if (existing == null || existing.isEmpty()) {
                bizPurchaseReturnService.generateFromInspectionPlan(
                    bizInspectionPlan.getPlanNo(),
                    bizInspectionPlan.getRejectedQuantity(),
                    bizInspectionPlan.getRejectionReason(),
                    null
                );
            }
            // 触发拒收回滚（含箱码置为拒收、订单与单据状态回退）
            rejectAndRollback(bizInspectionPlan.getPlanNo());
        }

        return rows;
    }

    /**
     * 批量删除来料检验计划
     * 
     * @param planIds 需要删除的来料检验计划主键
     * @return 结果
     */
    @Transactional
    @Override
    public int deleteBizInspectionPlanByPlanIds(Long[] planIds)
    {
        bizInspectionPlanMapper.deleteBizInspectionResultByPlanIds(planIds);
        return bizInspectionPlanMapper.deleteBizInspectionPlanByPlanIds(planIds);
    }

    /**
     * 删除来料检验计划信息
     * 
     * @param planId 来料检验计划主键
     * @return 结果
     */
    @Transactional
    @Override
    public int deleteBizInspectionPlanByPlanId(Long planId)
    {
        bizInspectionPlanMapper.deleteBizInspectionResultByPlanId(planId);
        return bizInspectionPlanMapper.deleteBizInspectionPlanByPlanId(planId);
    }

    /**
     * 检验拒收后回滚：将相关单据与订单回到生成箱码之前状态
     */
    @Transactional
    @Override
    public void rejectAndRollback(String planNo) {
        // 1) 查找检验计划
        BizInspectionPlan query = new BizInspectionPlan();
        query.setPlanNo(planNo);
        java.util.List<BizInspectionPlan> plans = bizInspectionPlanMapper.selectBizInspectionPlanList(query);
        if (plans == null || plans.isEmpty()) {
            throw new IllegalArgumentException("检验计划不存在: " + planNo);
        }
        BizInspectionPlan plan = plans.get(0);

        // 2) 找到该计划涉及的箱码（依据收料通知单号 + 批次号）
        com.ruoyi.system.domain.BizBarcode bcQuery = new com.ruoyi.system.domain.BizBarcode();
        bcQuery.setReceiptNoteNo(plan.getReceiptNoteNo());
        bcQuery.setBatchNo(plan.getBatchNo());
        java.util.List<com.ruoyi.system.domain.BizBarcode> barcodes = bizBarcodeMapper.selectBizBarcodeList(bcQuery);
        if (barcodes == null || barcodes.isEmpty()) {
            // 无箱码可回滚，仍需将单据状态置为拒收
            barcodes = new java.util.ArrayList<>();
        }

        java.util.Date now = com.ruoyi.common.utils.DateUtils.getNowDate();
        String username = com.ruoyi.common.utils.SecurityUtils.getUsername();

        // 3) 批量将箱码置为 REJECTED
        Long[] barcodeIds = barcodes.stream().map(com.ruoyi.system.domain.BizBarcode::getBarcodeId).filter(java.util.Objects::nonNull).toArray(Long[]::new);
        if (barcodeIds.length > 0) {
            bizBarcodeMapper.batchUpdateRejectedStatus(planNo, now, barcodeIds);
        }

        // 4) 统计各采购明细的回滚数量（按 itemId 汇总 packQuantity）并回写数量与状态
        java.util.Map<Long, java.math.BigDecimal> rollbackMap = new java.util.HashMap<>();
        for (com.ruoyi.system.domain.BizBarcode bc : barcodes) {
            if (bc.getItemId() == null) continue;
            java.math.BigDecimal qty = bc.getPackQuantity() == null ? java.math.BigDecimal.ZERO : bc.getPackQuantity();
            rollbackMap.merge(bc.getItemId(), qty, java.math.BigDecimal::add);
        }

        java.util.Set<Long> involvedOrderIds = new java.util.HashSet<>();
        for (java.util.Map.Entry<Long, java.math.BigDecimal> e : rollbackMap.entrySet()) {
            Long itemId = e.getKey();
            java.math.BigDecimal delta = e.getValue();
            com.ruoyi.system.domain.BizPurchaseOrderItem item = bizPurchaseOrderMapper.selectBizPurchaseOrderItemByItemId(itemId);
            if (item == null) continue;
            involvedOrderIds.add(item.getOrderId());
            java.math.BigDecimal curBarcoded = item.getBarcodedQuantity() == null ? java.math.BigDecimal.ZERO : item.getBarcodedQuantity();
            java.math.BigDecimal curUnbarcoded = item.getUnbarcodedQuantity() == null ? java.math.BigDecimal.ZERO : item.getUnbarcodedQuantity();
            java.math.BigDecimal newBarcoded = curBarcoded.subtract(delta);
            if (newBarcoded.compareTo(java.math.BigDecimal.ZERO) < 0) newBarcoded = java.math.BigDecimal.ZERO;
            java.math.BigDecimal newUnbarcoded = curUnbarcoded.add(delta);
            bizPurchaseOrderMapper.updateBizPurchaseOrderItemQuantities(itemId, newBarcoded, newUnbarcoded, username, now);
            // 回到打码前状态
            bizPurchaseOrderMapper.updateBizPurchaseOrderItemStatus(itemId, "PENDING", username, now);
        }

        // 5) 主表回滚汇总与状态
        for (Long orderId : involvedOrderIds) {
            bizPurchaseOrderMapper.updateBizPurchaseOrderHeaderBarcodedAndStatus(orderId, username, now);
        }

        // 6) 相关单据置为拒收
        if (com.ruoyi.common.utils.StringUtils.isNotEmpty(plan.getReceiptNoteNo())) {
            com.ruoyi.system.domain.BizReceiptNote rnQ = new com.ruoyi.system.domain.BizReceiptNote();
            rnQ.setReceiptNoteNo(plan.getReceiptNoteNo());
            java.util.List<com.ruoyi.system.domain.BizReceiptNote> rnList = bizReceiptNoteMapper.selectBizReceiptNoteList(rnQ);
            if (rnList != null && !rnList.isEmpty()) {
                com.ruoyi.system.domain.BizReceiptNote rn = rnList.get(0);
                rn.setReceiptStatus("REJECTED");
                rn.setQualityResult("FAILED");
                rn.setUpdatedBy(username);
                rn.setUpdatedTime(now);
                bizReceiptNoteMapper.updateBizReceiptNote(rn);
            }
        }
        if (com.ruoyi.common.utils.StringUtils.isNotEmpty(plan.getDeliveryNoteNo())) {
            com.ruoyi.system.domain.BizDeliveryNote dnQ = new com.ruoyi.system.domain.BizDeliveryNote();
            dnQ.setDeliveryNoteNo(plan.getDeliveryNoteNo());
            java.util.List<com.ruoyi.system.domain.BizDeliveryNote> dnList = bizDeliveryNoteMapper.selectBizDeliveryNoteList(dnQ);
            if (dnList != null && !dnList.isEmpty()) {
                com.ruoyi.system.domain.BizDeliveryNote dn = dnList.get(0);
                dn.setDeliveryStatus("REJECTED");
                dn.setUpdatedBy(username);
                dn.setUpdatedTime(now);
                bizDeliveryNoteMapper.updateBizDeliveryNote(dn);
                // 同步批次状态（若有批次号）
                if (com.ruoyi.common.utils.StringUtils.isNotEmpty(plan.getBatchNo())) {
                    bizDeliveryNoteMapper.updateBizDeliveryBatchStatusByNoteIdAndBatchNo(dn.getDeliveryNoteId(), plan.getBatchNo(), "REJECTED", username, now);
                }
            }
        }

        // 7) 更新检验计划自身状态为 REJECTED
        plan.setPlanStatus("REJECTED");
        plan.setUpdatedBy(username);
        plan.setUpdatedTime(now);
        bizInspectionPlanMapper.updateBizInspectionPlan(plan);
    }

    /**
     * 新增检验结果明细信息
     * 
     * @param bizInspectionPlan 来料检验计划对象
     */
    public void insertBizInspectionResult(BizInspectionPlan bizInspectionPlan)
    {
        List<BizInspectionResult> bizInspectionResultList = bizInspectionPlan.getBizInspectionResultList();
        Long planId = bizInspectionPlan.getPlanId();
        if (StringUtils.isNotNull(bizInspectionResultList))
        {
            List<BizInspectionResult> list = new ArrayList<BizInspectionResult>();
            for (BizInspectionResult bizInspectionResult : bizInspectionResultList)
            {
                bizInspectionResult.setPlanId(planId);
                list.add(bizInspectionResult);
            }
            if (list.size() > 0)
            {
                bizInspectionPlanMapper.batchBizInspectionResult(list);
            }
        }
    }
}
